﻿using System;
using System.Collections.Generic;
using System.Text;
using Gammar.Digger.DALFactory;
using Gammar.Digger.Entity;
using Gammar.Digger.SystemFramework;
using Gammar.Digger.IDAL;
using System.Xml;
using System.Reflection;
using System.Web;
namespace Gammar.Digger.BLL
{
    public class PluginValidate
    {
        /// <summary>
        /// 插件校验结果
        /// </summary>
       public enum Result
        {
            /// <summary>
            /// 有效
            /// </summary>
            valid,
            /// <summary>
            /// 无效
            /// </summary>
            invalid,

            /// <summary>
            /// url无效
            /// </summary>
            UrlInvalid,
                
            /// <summary>
            /// 匹配失败
            /// </summary>
            MatchFailed,

            /// <summary>
            /// 未找到相关插件
            /// </summary>
            NotFind
        }

        /// <summary>
        /// 每项的校验结果
        /// </summary>
        public enum ItemResult
        {
            /// <summary>
            /// 有效
            /// </summary>
            valid,
            /// <summary>
            /// 无效
            /// </summary>
            invalid,
            /// <summary>
            /// 未知状态
            /// </summary>
            unknown,

             /// <summary>
            /// url无效
            /// </summary>
            UrlInvalid,
                
            /// <summary>
            /// 匹配失败
            /// </summary>
            MatchFailed,

            /// <summary>
            /// 匹配规则为空
            /// </summary>
            Isnull
        }

        public class PluginValidResult
        {
            public string PluginName { get; set; }
            public int PluginId { get; set; }
            public Result Result { get; set; }
            public string StartUrl { get; set; }
            public string DetailUrl { get; set; }
            public Dictionary<string, ItemResult> ItemResults = new Dictionary<string, ItemResult>();
        }

       
        public static PluginValidResult DoValid(string pluginId)
        {
            PluginValidResult result = new PluginValidResult();
            result.PluginId = int.Parse(pluginId);
            digger_pluginEntity plugin = PluginManagement.GetPluginById(pluginId);

            if (plugin!=null)
            {
                string startUrl =result.StartUrl =plugin.start_url;

                WebHelper webhelper = new WebHelper();

                //起始页校验
                Encoding encode = null;
                if (!string.IsNullOrEmpty(plugin.page_Encode))
                {
                    encode = Encoding.GetEncoding(plugin.page_Encode);
                }

                string startPageSource = webhelper.GetSource(startUrl, encode);
                if (string.IsNullOrEmpty(startPageSource))
                {
                    //起始页为空
                    result.Result = Result.NotFind;

                    result.ItemResults.Add("start_url", ItemResult.UrlInvalid);
                
                }
                else
                {
                    result.ItemResults.Add("start_url", ItemResult.valid);

                    //起始页不为空，匹配列表、下一页、详情页等信息
                    
                    //list_area_rule
                    Match(startPageSource, "list_area_rule", plugin.list_area_rule, result);

                    //list_url_rule
                    Match(startPageSource, "list_url_rule", plugin.list_url_rule, result);

                    //list_nextPage_rule
                    Match(startPageSource, "list_nextPage_rule", plugin.list_nextPage_rule, result);

                    //content_url_rule
                    List<string> matchedResult=new List<string>();
                    Match(startPageSource, "content_url_rule", plugin.content_url_rule, result, ref matchedResult);

                    if (matchedResult.Count>0)
                    {
                        //获取详情页source
                       // result.DetailUrl = webhelper.FormatUrl(plugin.start_url,matchedResult[0]);

                        int errortimes = matchedResult.Count > 3 ? 3 : matchedResult.Count;

                        int errorCount = 0;
                        foreach (string detailUrl in matchedResult)
                        {
                            if (errorCount==errortimes)
                            {
                                break;
                            }

                            string fullDetailUrl = webhelper.FormatUrl(plugin.start_url, detailUrl);
                            string detailSource = webhelper.GetSource(fullDetailUrl,encode);
                            if (string.IsNullOrEmpty(detailSource))
                            {
                                result.ItemResults["content_url_rule"] = ItemResult.UrlInvalid;
                            }
                            else
                            {
                                /*匹配每个item
                                content_nextPage_rule
                                content_title_rule
                                content_detail_rule
                                content_originalPrice_rule
                                content_salePrice_rule
                                content_CreateDate_rule
                                 * 
                                 */
                                Match(detailSource, "content_CreateDate_rule", plugin.content_CreateDate_rule, result);
                                // Match(detailSource, plugin.content_detail_rule);
                                Match(detailSource, "content_nextPage_rule", plugin.content_nextPage_rule, result);
                                Match(detailSource, "content_originalPrice_rule", plugin.content_originalPrice_rule, result);
                                Match(detailSource, "content_salePrice_rule", plugin.content_salePrice_rule, result);
                                Match(detailSource, "content_title_rule", plugin.content_title_rule, result);

                                XmlDocument xdoc = new XmlDocument();
                                xdoc.LoadXml(plugin.content_detail_rule);

                                XmlNode root = xdoc.GetElementsByTagName("root")[0];
                                foreach (XmlNode node in root.ChildNodes)
                                {
                                    Match(detailSource, node.Name, node.InnerText, result);
                                }

                            }

                            if (result.ItemResults.ContainsValue(ItemResult.MatchFailed) || result.ItemResults.ContainsValue(ItemResult.invalid) || result.ItemResults.ContainsValue(ItemResult.UrlInvalid))
                            {
                                errorCount++;
                                result.DetailUrl = result.DetailUrl == string.Empty ? fullDetailUrl : result.DetailUrl + "<br>" + fullDetailUrl;
                            }
                            else
                            {
                                result.DetailUrl = result.DetailUrl == string.Empty ? fullDetailUrl : result.DetailUrl + "<br>" + fullDetailUrl;
                                break;
                            }

                        }

                     

                    }

                    if (result.ItemResults.ContainsValue(ItemResult.MatchFailed)||result.ItemResults.ContainsValue(ItemResult.invalid)||result.ItemResults.ContainsValue(ItemResult.UrlInvalid))
                    {
                        result.Result = Result.invalid;
                    }
                    
                    
                }
            }
            else
            {
                result.Result = Result.NotFind;
            }

            return result;
        }

        /// <summary>
        /// 匹配文本，如果失败超过3次，不再重试
        /// </summary>
        /// <param name="itemName"></param>
        /// <param name="itemRule"></param>
        /// <returns></returns>
        private static ItemResult TryMatch(string sourcePage, string itemRule,ref List<string> matchedResult)
        {
            ItemResult reval = ItemResult.unknown;

            if (string.IsNullOrEmpty(itemRule))
            {
                return ItemResult.Isnull;
            }
            WebHelper helper = new WebHelper();
            int time = 3;
            while (time>0)
            {
               List<string> result= helper.MathString(sourcePage, itemRule);
               if (result.Count>0)
               {
                   reval = ItemResult.valid;
                   if (matchedResult!=null)
                   {
                       matchedResult = result;
                   }
                   break;
               }
               else
               {
                   time--;
                   if (time==1)
                   {
                        reval = ItemResult.MatchFailed;
                   }
                  
               }
            }
            return reval;
        }

        private static void Match(string sourcePage,string itemName, string itemRule, PluginValidResult result)
        {
            List<string> list = null;
            ItemResult reval = TryMatch(sourcePage, itemRule,ref list);
           // itemRule.GetType().
            if (result.ItemResults.ContainsKey(itemName))
            {
                result.ItemResults[itemName] = reval;
            }
            else
            {
                result.ItemResults.Add(itemName, reval);
            }
        }

        private static void Match(string sourcePage, string itemName, string itemRule, PluginValidResult result, ref List<string> matchedResult)
        {
            ItemResult reval = TryMatch(sourcePage, itemRule, ref matchedResult);
            result.ItemResults.Add(itemName, reval);
        }


        public static string FormatResult(Result result)
        {
            if (result== Result.valid)
            {
                return "<font color=blue>" + result.ToString() + "</font>";
            }
            else
            {
                return "<font color=Red>" + result.ToString() + "</font>";
            }
        }

        public static string FormatItemResult(ItemResult result)
        {
            if (result == ItemResult.valid)
            {
                return "<font color=blue>" + result.ToString() + "</font>";
            }
            else if (result == ItemResult.Isnull || result == ItemResult.unknown)
            {
                return "<font color=Green>" + result.ToString() + "</font>";
            }
            else
            {
                return "<font color=Red>" + result.ToString() + "</font>";
            }
        }

    }
}
